.. role:: raw-html-m2r(raw)
:format: html
VHDL and Verilog generation
===========================
Generate VHDL and Verilog from a SpinalHDL Component
-----------------------------------------------------
To generate the VHDL from a SpinalHDL component you just need to call ``SpinalVhdl(new YourComponent)`` in a Scala ``main``.
Generating Verilog is exactly the same, but with ``SpinalVerilog`` in place of ``SpinalVHDL``
.. code-block:: scala
import spinal.core._
// A simple component definition.
class MyTopLevel extends Component {
// Define some input/output signals. Bundle like a VHDL record or a Verilog struct.
val io = new Bundle {
val a = in Bool()
val b = in Bool()
val c = out Bool()
}
// Define some asynchronous logic.
io.c := io.a & io.b
}
// This is the main function that generates the VHDL and the Verilog corresponding to MyTopLevel.
object MyMain {
def main(args: Array[String]) {
SpinalVhdl(new MyTopLevel)
SpinalVerilog(new MyTopLevel)
}
}
.. important::
``SpinalVhdl`` and ``SpinalVerilog`` may need to create multiple instances of your component class, therefore the first argument is not a ``Component`` reference, but a function that returns a new component.
.. important::
The ``SpinalVerilog`` implementation began the 5th of June, 2016.
This backend successfully passes the same regression tests as the VHDL one (RISCV CPU, Multicore and pipelined mandelbrot, UART RX/TX, Single clock fifo, Dual clock fifo, Gray counter, ...).
If you have any issues with this new backend, please make a `Github issue `_ describing the problem.
Parametrization from Scala
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: 1 1 1 5
* - Argument name
- Type
- Default
- Description
* - ``mode``
- SpinalMode
- null
- | Set the SpinalHDL hdl generation mode.
| Can be set to ``VHDL`` or ``Verilog``
* - ``defaultConfigForClockDomains``
- ClockDomainConfig
- | RisingEdgeClock
| AsynchronousReset
| ResetActiveHigh
| ClockEnableActiveHigh
- Set the clock configuration that will be used as the default value for all new ``ClockDomain``.
* - ``onlyStdLogicVectorAtTopLevelIo``
- Boolean
- false
- Change all unsigned/signed toplevel io into std_logic_vector.
* - ``defaultClockDomainFrequency``
- IClockDomainFrequency
- UnknownFrequency
- Default clock frequency.
* - ``targetDirectory``
- String
- Current directory
- Directory where files are generated.
And this is the syntax to specify them:
.. code-block:: scala
SpinalConfig(mode=VHDL, targetDirectory="temp/myDesign").generate(new UartCtrl)
// Or for Verilog in a more scalable formatting:
SpinalConfig(
mode=Verilog,
targetDirectory="temp/myDesign"
).generate(new UartCtrl)
Parametrization from shell
^^^^^^^^^^^^^^^^^^^^^^^^^^
You can also specify generation parameters by using command line arguments.
.. code-block:: scala
def main(args: Array[String]): Unit = {
SpinalConfig.shell(args)(new UartCtrl)
}
The syntax for command line arguments is:
.. code-block:: text
Usage: SpinalCore [options]
--vhdl
Select the VHDL mode
--verilog
Select the Verilog mode
-d | --debug
Enter in debug mode directly
-o | --targetDirectory
Set the target directory
Generated VHDL and Verilog
--------------------------
How a SpinalHDL RTL description is translated into VHDL and Verilog is important:
* Names in Scala are preserved in VHDL and Verilog.
* ``Component`` hierarchy in Scala is preserved in VHDL and Verilog.
* ``when`` statements in Scala are emitted as if statements in VHDL and Verilog.
* ``switch`` statements in Scala are emitted as case statements in VHDL and Verilog in all standard cases.
Organization
^^^^^^^^^^^^
When you use the VHDL generator, all modules are generated into a single file which contain three sections:
#. A package that contains the definition of all Enums
#. A package that contains functions used by the architectural elements
#. All components needed by your design
When you use the Verilog generation, all modules are generated into a single file which contains two sections:
#. All enumeration definitions used
#. All modules needed by your design
Combinational logic
^^^^^^^^^^^^^^^^^^^
Scala:
.. code-block:: scala
class TopLevel extends Component {
val io = new Bundle {
val cond = in Bool()
val value = in UInt(4 bits)
val withoutProcess = out UInt(4 bits)
val withProcess = out UInt(4 bits)
}
io.withoutProcess := io.value
io.withProcess := 0
when(io.cond) {
switch(io.value) {
is(U"0000") {
io.withProcess := 8
}
is(U"0001") {
io.withProcess := 9
}
default {
io.withProcess := io.value+1
}
}
}
}
VHDL:
.. code-block:: vhdl
entity TopLevel is
port(
io_cond : in std_logic;
io_value : in unsigned(3 downto 0);
io_withoutProcess : out unsigned(3 downto 0);
io_withProcess : out unsigned(3 downto 0)
);
end TopLevel;
architecture arch of TopLevel is
begin
io_withoutProcess <= io_value;
process(io_cond,io_value)
begin
io_withProcess <= pkg_unsigned("0000");
if io_cond = '1' then
case io_value is
when pkg_unsigned("0000") =>
io_withProcess <= pkg_unsigned("1000");
when pkg_unsigned("0001") =>
io_withProcess <= pkg_unsigned("1001");
when others =>
io_withProcess <= (io_value + pkg_unsigned("0001"));
end case;
end if;
end process;
end arch;
Sequential logic
^^^^^^^^^^^^^^^^
Scala:
.. code-block:: scala
class TopLevel extends Component {
val io = new Bundle {
val cond = in Bool()
val value = in UInt (4 bit)
val resultA = out UInt(4 bit)
val resultB = out UInt(4 bit)
}
val regWithReset = Reg(UInt(4 bits)) init(0)
val regWithoutReset = Reg(UInt(4 bits))
regWithReset := io.value
regWithoutReset := 0
when(io.cond) {
regWithoutReset := io.value
}
io.resultA := regWithReset
io.resultB := regWithoutReset
}
VHDL:
.. code-block:: vhdl
entity TopLevel is
port(
io_cond : in std_logic;
io_value : in unsigned(3 downto 0);
io_resultA : out unsigned(3 downto 0);
io_resultB : out unsigned(3 downto 0);
clk : in std_logic;
reset : in std_logic
);
end TopLevel;
architecture arch of TopLevel is
signal regWithReset : unsigned(3 downto 0);
signal regWithoutReset : unsigned(3 downto 0);
begin
io_resultA <= regWithReset;
io_resultB <= regWithoutReset;
process(clk,reset)
begin
if reset = '1' then
regWithReset <= pkg_unsigned("0000");
elsif rising_edge(clk) then
regWithReset <= io_value;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
regWithoutReset <= pkg_unsigned("0000");
if io_cond = '1' then
regWithoutReset <= io_value;
end if;
end if;
end process;
end arch;
VHDL and Verilog attributes
---------------------------
In some situations, it is useful to give attributes for some signals in a design to modify how they are synthesized.
To do that, you can call the following functions on any signals or memories in the design:
.. list-table::
:header-rows: 1
:widths: 1 2
* - Syntax
- Description
* - ``addAttribute(name)``
- Add a boolean attribute with the given ``name`` set to true
* - ``addAttribute(name, value)``
- Add a string attribute with the given ``name`` set to ``value``
Example:
.. code-block:: scala
val pcPlus4 = pc + 4
pcPlus4.addAttribute("keep")
Produced declaration in VHDL:
.. code-block:: vhdl
attribute keep : boolean;
signal pcPlus4 : unsigned(31 downto 0);
attribute keep of pcPlus4: signal is true;
Produced declaration in Verilog:
.. code-block:: verilog
(* keep *) wire [31:0] pcPlus4;